using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.IO;

namespace DCApp
{

    /// <summary>
    /// This class implements the functionality to store all the Participant 
    /// information into a local xml file.  
    /// </summary>
    class XmlStore
    {
        private const string _xmlFileName = "dc_data.xml";

        private static string GetXmlFileFullPath()
        {
            string assembly_path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            string directory_path = Path.GetDirectoryName(assembly_path);
            string xml_path = Path.Combine(directory_path,_xmlFileName);
            return xml_path;
        }

        private static void StoreDataSetToXml(DataSet ds)
        {
            string xml_path = GetXmlFileFullPath();
            ds.WriteXml(xml_path, XmlWriteMode.WriteSchema);
        }


        /// <summary>
        /// Construct the DataSet from Xml storage
        /// </summary>
        /// <returns>DataSet of the Xml stored</returns>
        public static DataSet ConstructDataSetFromXml()
        {
            string xml_path = GetXmlFileFullPath();
            if (!File.Exists(xml_path))
            {
                //If the file does not exist. (application run for first time)
                //Create the xml file
                CreateDataSetXmlSource();
            }

            DataSet ds = new DataSet();
            try
            {
                ds.ReadXml(xml_path);
            }
            catch (System.Exception e)
            {
                string errorMessage = "An error occured while reading participant data from " + xml_path;
                errorMessage += "\r\n\r\nError:" + e.Message;
                errorMessage += "\r\n\r\nIf the error persists, delete the above file and try again.";
                System.Windows.Forms.MessageBox.Show(errorMessage);
                throw;
            }

            return ds;
        }


        /// <summary>
        /// Creates the xml storage file with an empty dataset of the required schema
        /// </summary>
        private static void CreateDataSetXmlSource()
        {
            DataSet ds = new DataSet("DCAppData");

            DataTable objTable = new DataTable("Participants");

            DataColumn col_1 = new DataColumn("MyAppSpecificParticipantId", typeof(string));
            DataColumn col_2 = new DataColumn("ParticipantName", typeof(string));
            DataColumn col_3 = new DataColumn("DateTokenGenerated", typeof(DateTime));
            DataColumn col_4 = new DataColumn("ParticipantCode", typeof(string));
            DataColumn col_5 = new DataColumn("SecurityQuestion", typeof(string));
            DataColumn col_6 = new DataColumn("SecurityAnswer", typeof(string));
            DataColumn col_7 = new DataColumn("HasAuthorized", typeof(bool));
            DataColumn col_8 = new DataColumn("PersonId", typeof(Guid));
            DataColumn col_9 = new DataColumn("RecordId", typeof(Guid));
            
            objTable.Columns.Add(col_1);
            objTable.Columns.Add(col_2);
            objTable.Columns.Add(col_3);
            objTable.Columns.Add(col_4);
            objTable.Columns.Add(col_5);
            objTable.Columns.Add(col_6);
            objTable.Columns.Add(col_7);
            objTable.Columns.Add(col_8);
            objTable.Columns.Add(col_9);

            ds.Tables.Add(objTable);
            StoreDataSetToXml(ds);
        }


        /// <summary>
        /// Adds a participant to the xml data storage
        /// </summary>
        /// <param name="appSpecificParticipantId">The application specific identifier for the participant.</param>
        /// <param name="participantName">Name of the participant</param>
        /// <param name="dateTokenGenerated">Date time of registration</param>
        /// <param name="participantCode">A token that the participant should use when authorizing this application to use his healthrecord</param>
        /// <param name="securityQuestion">The security question agreed upon</param>
        /// <param name="securityAnswer">The security answer agreed upon</param>
        public static void AddParticipantToLocalStore(string appSpecificParticipantId, 
            string participantName, 
            DateTime dateTokenGenerated,
            string participantCode,
            string securityQuestion,
            string securityAnswer)
        {
            //Construct the dataset from XML first
            DataSet ds = ConstructDataSetFromXml();

            //Add rows to the table in dataset
            DataTable objTable = ds.Tables[0];
            DataRow newRow = objTable.NewRow();
            newRow["MyAppSpecificParticipantId"] = appSpecificParticipantId;
            newRow["ParticipantName"] = participantName;
            newRow["DateTokenGenerated"] = dateTokenGenerated;
            newRow["ParticipantCode"] = participantCode;
            newRow["SecurityQuestion"] = securityQuestion;
            newRow["SecurityAnswer"] = securityAnswer;
            newRow["HasAuthorized"] = false;

            objTable.Rows.Add(newRow);

            //Store the dataset back to xml
            StoreDataSetToXml(ds);
        }


        /// <summary>
        /// Changes the status of a participant once he has authorized the application access in HealthVault shell
        /// Specifically, updates the participant record in the xml with PersonId, RecordId and sets the HasAuthorized flag to true
        /// /// </summary>
        /// <param name="appSpecificParticipantId">The application specific identifier for the participant.</param>
        /// <param name="personId">The PersonId that needs to be used in future offline access to this participant record</param>
        /// <param name="recordId">The RecordId that needs to be used in future offline access to this participant record</param>
        public static void UpdateParticipantToAuthorizedStatus(string appSpecificParticipantId, string personId, string recordId)
        {
            DataSet ds = ConstructDataSetFromXml();
            DataTable objTable = ds.Tables[0];

            DataRow[] matchingRows = objTable.Select("MyAppSpecificParticipantId='" + appSpecificParticipantId.ToString() + "'");
            if (matchingRows.Length > 0)
            {
                DataRow rowToUpdate = matchingRows[0];
                rowToUpdate["PersonId"] = personId;
                rowToUpdate["RecordId"] = recordId;
                rowToUpdate["HasAuthorized"] = true;
            }
            StoreDataSetToXml(ds);
        }


        /// <summary>
        /// Returns the details of a participant in a DataRow corresponding to a participant
        /// </summary>
        /// <param name="appSpecificParticipantId">The application specific identifier for the participant.</param>
        /// <returns>DataRow populated with participant data</returns>
        public static DataRow FetchParticipantFromLocalStore(string appSpecificParticipantId)
        {
            DataSet ds = ConstructDataSetFromXml();
            DataTable objTable = ds.Tables[0];

            DataRow[] matchingRows = objTable.Select("MyAppSpecificParticipantId='" + appSpecificParticipantId.ToString() + "'");
            if (matchingRows.Length > 0)
            {
                DataRow rowToReturn = matchingRows[0];
                return rowToReturn;
            }
            return null;
        }

    }
}
